package paths.g4;

import java.util.*;

import paths.*;

public class ZoomIn {

	public class Area{
		float x;
		float y;
		float width;
		float height;
		String name;
		
		public Area(){			
		}
		public Area( Area A){
			x = A.x;
			y = A.y;
			width = A.width;
			height = A.height;
			name = A.name;
		}
		public Area(float x, float y, float width, float height){
			this.x = x;
			this.y = y;
			this.width = width;
			this.height = height;
		}
		public Area(float x, float y, float width, float height, String name){
			this.x = x;
			this.y = y;
			this.width = width;
			this.height = height;
			this.name = name;
		}
	}
	
  Area Australia = new Area(113, -5, 65, 38, "Australian");
	Area WestEuro = new Area( -5, 57, 30, 20, "Western European"); 
	Area EastUS = new Area(-85, 46, 30, 20, "Eastern United States");
  Area WestUS = new Area(-130, 50, 30, 20, "Western United States");

	Area India = new Area(68, 35, 30, 30, "Indian");
	Area EastSouthAsia = new Area(110, 45, 30, 25, "Eastern South Asian");
	Area EastAsia = new Area(100, 20, 30, 25, "Eastern Asian");
	Area Africa = new Area(-5, -5, 30, 30, "Southern African");
	Area SouthAmerica = new Area(-70, -2, 30, 30, "Central South American");

	ArrayList<Area> AreaList = new ArrayList<Area>();
	final int MAX_AREA_NUM = 20;
	//no more than 20 areas
	int areaNum = 4;
	

	private boolean checkInArea(float x, float y, Area A){
		boolean flag = false;
		float xMax = A.x + A.width;
		float yMin = A.y - A.height;
		
		if(xMax<180){
			if( x>A.x && x<xMax && y<A.y && y>yMin){
				flag = true;
			}
			
		}
		else{ //xMax>=180
			if( ( (x>A.x && x<180) || (x>=-180 && x>xMax)) 
					&& y<A.y && y>yMin){
				flag = true;
			}
			
		}
		return flag;
	}

	private int[] findAreaCityNum(ArrayList<City> cities, boolean cityReach[]){
		int[] cityNum = new int[MAX_AREA_NUM];
		
		int index = 0;
		
		for(int i=0; i<areaNum; i++)
			cityNum[i] = 0;
		
		for(int i=0; i<cities.size(); i++){
//			if(in_degree[i] > 0){  //there is this city in reach list
			if( cityReach[i]){  //there is this city in reach list
				float x = cities.get(i).x;
				float y = cities.get(i).y;
				
				index = MAX_AREA_NUM;
				for(int j=0; j<AreaList.size(); j++){
					if(checkInArea(x, y, AreaList.get(j))){
						index = j;
						cityNum[index] ++;
	//					break;
					}					
				}
			}
		}
		return cityNum;
	}
	
	private int[] findAreaLinkNum(ArrayList<City> cities, int in_degree[]){
		int[] linkNum = new int[MAX_AREA_NUM];
		
		int index = 0;
		
		for(int i=0; i<areaNum; i++)
			linkNum[i] = 0;
		
		for(int i=0; i<cities.size(); i++){
			if( in_degree[i] > 0){  //there is link in the city
				float x = cities.get(i).x;
				float y = cities.get(i).y;
				
				index = MAX_AREA_NUM;
				for(int j=0; j<AreaList.size(); j++){
					if(checkInArea(x, y, AreaList.get(j))){
						index = j;
						linkNum[index] += in_degree[i];
//						break;
					}					
				}
				
			}
		}
		return linkNum;
	}
	

	public Area findCrowdArea(ArrayList<City> cities, 
			boolean cityReach[], int in_degree[]){

		int index = 0;

		AreaList.add(Australia);
		AreaList.add(WestEuro);
		AreaList.add(EastUS);
		AreaList.add(WestUS);
		AreaList.add(India);
		AreaList.add(EastSouthAsia);
		AreaList.add(EastAsia);
		AreaList.add(Africa);
		AreaList.add(SouthAmerica);

		areaNum = AreaList.size();
		
		int[] cityNum = findAreaCityNum(cities, cityReach);
		int[] linkNum = findAreaLinkNum(cities, in_degree);
		
//		float[] density = new float[areaNum];
	
		//compare the density to pick up the crowed area
//		for(int i=0; i<areaNum; i++){
//			Area area = AreaList.get(i);
//			density[i] = cityNum[i] / (area.height*area.width);
//			if(i>0){
//				if (density[i] > density[index])
//					index = i;
//			}
//		}
		
		final int SHRESH_CITY_NUM = 3;
		final int SHRESH_LINK_NUM = 8;
		//compare the city and link number to pick up the crowed area
		//if city number difference is larger than 3, pick the larger
		//else, if city numbers differ less than 3
		//find the link number larger than 8
		//if not, choose the city with two larger number
		//otherwise, keep the current area
		for(int i=0; i<areaNum; i++){
			if(i>0){
				if (cityNum[i] - cityNum[index] > SHRESH_CITY_NUM)
					index = i;
				else if(cityNum[index] - cityNum[i] <= SHRESH_CITY_NUM){
					if(linkNum[i] - linkNum[index] > SHRESH_LINK_NUM)
						index = i;
					else if(cityNum[i]>cityNum[index] && linkNum[index]<linkNum[i])
						index = i;
				}
			}
		}
		
		//if the number of city and link is too small, zoom in no area 
		if(cityNum[index]<3 && linkNum[index]<5)
			return null;

		return AreaList.get(index);
	}
}

